home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / NDK / NDK_3.5 / Tutorials / Printer / Deutsch / Applikationen.dok < prev    next >
Encoding:
Text File  |  1999-10-11  |  19.2 KB  |  485 lines

  1.  
  2. printer.device V44 (OS 3.5)
  3.  
  4. Änderungen
  5.  
  6. Übersicht
  7.  
  8. · bis 10 Units mit getrennten Benutzereinstellungen
  9.  
  10. · Unterstützung der RTG Systeme mit CyberGfx API
  11.  
  12. · vereinfachte und erweiterte Fehlerbehandlung
  13.  
  14. · flexible Treibererweiterungen durch Taglisten
  15.  
  16. · erweiterte Möglichkeiten für den Treiber für Farbkonvertierung und
  17.   Farbkorrektur
  18.  
  19. · 24 Bit Farbraum (16 Millionen Farben) für Druckertreiber
  20.  
  21. · flexiblere Druckereinstellungen durch Treiber steuerbar
  22.  
  23.  
  24. Änderungen für die Druckereinstellungen
  25.  
  26. Die neue Version des printer.device bringt einige Änderungen für die
  27. Druckereinstellungen (Preferences) mit.
  28.  
  29. 1. Das printer.device unterstützt bis 10 Units, jede Unit hat eigene
  30. Einstellungen, die der Benutzer mit dem Voreinsteller "Printer" festlegt.
  31. Öffnen des printer.device und Auslesen der Einstellungen funktioniert wie
  32. bisher, nur eben für die Units 0 bis 9. Für die Auswahl der Unit gibt
  33. es zwei Möglichkeiten:
  34.  
  35. A. Eine einfache Auswahl über eine Nummer 0 bis 9, z.B. als Zahleingabefeld.
  36.  
  37. B. Die komfortable Auswahl über ein Popup-Menü o.ä. mit den Namen die der
  38. Benutzer für jede Unit vergeben kann. Dazu müssen die Preferencesdateien
  39. ENV:Sys/printer.prefs (für Unit 0) und ENV:Sys/printer1.prefs bis
  40. ENV:Sys/printer9.prefs gelesen werden. Diese Dateien sind alles IFF Dateien
  41. und enthalten möglicherweise eine FORM PDEV. Die FORM enthält dann eine
  42. folgende Struktur (Includedatei prefs/printertxt.h):
  43.  
  44. struct PrinterDeviceUnitPrefs
  45. {
  46.     LONG    pd_Reserved[4];
  47.     LONG    pd_UnitNum;
  48.     UBYTE    pd_UnitName[UNITNAMESIZE];
  49. };
  50.  
  51. Das Feld pd_UnitNum enthält nochmal die Nummer der Unit, das Feld pd_UnitName
  52. enthält den symbolischen Name. Dieser String kann allerdings leer sein
  53. (pd_UnitName[0] == 0), dann muß ein Ersatztext benutzt werden (zum Beispiel
  54. Unit N, wobei N durch die Nummer der Unit ersetzt wird).
  55.  
  56. Das folgende Programm liest die Namen aller 10 Units aus der Preferences
  57. Datei aus und gibt sie in der Konsole aus. Der Name wird durch den Text
  58. "Unit N" (wobei N die Unitnummer ist) ersetzt, falls der Benutzer keinen
  59. Namen für die Unit angegeben hat.
  60.  
  61. /* includes */
  62. #include <dos/dos.h>
  63. #include <libraries/iffparse.h>
  64. #include <prefs/prefhdr.h>
  65. #include <prefs/printertxt.h>
  66.  
  67. /* prototypes */
  68. #include <clib/iffparse_protos.h>
  69. #include <clib/dos_protos.h>
  70. #include <clib/alib_protos.h>
  71. #include <clib/alib_stdio_protos.h>
  72. #include <string.h>
  73.  
  74. BPTR stdout;
  75.  
  76. /*****************************************************************************/
  77.  
  78. #define IFFPrefChunkCnt 2
  79. static LONG IFFPrefChunks[] =
  80. {
  81.     ID_PREF, ID_PRHD,
  82.     ID_PREF, ID_PDEV,
  83. };
  84.  
  85. void ReadUnitName(char *filename, char name[], int unitnum)
  86. {
  87.     BPTR fp;
  88.     BOOL ok;
  89.     struct IFFHandle *iff;
  90.     struct ContextNode *cn;
  91.     struct PrefHeader phead;
  92.     struct PrinterDeviceUnitPrefs pdev;
  93.  
  94.     sprintf(name,"Unit %ld",unitnum);
  95.     if (fp = Open(filename, MODE_OLDFILE))
  96.     {
  97.         if (iff = AllocIFF())
  98.         {
  99.             iff->iff_Stream = fp;
  100.             InitIFFasDOS(iff);
  101.  
  102.             if (!OpenIFF(iff, IFFF_READ))
  103.             {
  104.                 if (!ParseIFF(iff, IFFPARSE_STEP))
  105.                 {
  106.                     cn = CurrentChunk(iff);
  107.                     if (cn->cn_ID == ID_FORM && cn->cn_Type == ID_PREF)
  108.                     {
  109.                         if (!StopChunks(iff, IFFPrefChunks, IFFPrefChunkCnt))
  110.                         {
  111.                             ok = TRUE;
  112.                             while (ok)
  113.                             {
  114.                                 if (ParseIFF(iff, IFFPARSE_SCAN))
  115.                                     break;
  116.                                 cn = CurrentChunk(iff);
  117.                                 if (cn->cn_Type == ID_PREF)
  118.                                 {
  119.                                     switch (cn->cn_ID)
  120.                                     {
  121.                                         case ID_PRHD:
  122.                                             if (ReadChunkBytes(iff, &phead, sizeof(struct PrefHeader)) != sizeof(struct PrefHeader))
  123.                                             {
  124.                                                 ok = FALSE;
  125.                                                 break;
  126.                                             }
  127.                                             if (phead.ph_Version != 0)
  128.                                             {
  129.                                                 ok = FALSE;
  130.                                                 break;
  131.                                             }
  132.                                             break;
  133.                                         case ID_PDEV:
  134.                                             if (ReadChunkBytes(iff, &pdev, sizeof(pdev)) == sizeof(pdev))
  135.                                             {
  136.                                                 if (pdev.pd_UnitName[0])
  137.                                                     strcpy(name,pdev.pd_UnitName);
  138.                                             }
  139.                                             break;
  140.                                         default:
  141.                                             break;
  142.                                     }
  143.                                 }
  144.                             }
  145.                         }
  146.                     }
  147.                 }
  148.                 CloseIFF(iff);
  149.             }
  150.             FreeIFF(iff);
  151.         }
  152.         Close(fp);
  153.     }
  154. }
  155.  
  156. void main(void)
  157. {
  158.     char filename[30];
  159.     char name[UNITNAMESIZE];
  160.     int i;
  161.  
  162.     stdout = Output();
  163.     ReadUnitName("ENV:Sys/printer.prefs",name,0);
  164.     printf("Printer Unit Names:\n 0: %s\n",name);
  165.     strcpy(filename,"ENV:Sys/printerN.prefs");
  166.     for (i = 1; i < 10; i++)
  167.     {
  168.         filename[15] = '0' + i;
  169.         ReadUnitName(filename,name,i);
  170.         printf(" %ld: %s\n",i,name);
  171.     }
  172. }
  173.  
  174. Eine Applikation sollte diese Liste nicht nur bei Programmstart, sondern
  175. vor jedem Drucken neu einlesen, z.B. beim Öffnen des Druckerdialogs. Damit
  176. spiegelt die Liste alle Namensänderungen, die der Benutzer inzwischen an den
  177. Preferences gemacht haben kann wieder.
  178.  
  179.  
  180. 2. In der Vergangenheit hat sich gezeigt, daß die Druckereinstellungen nicht
  181. umfassend genug sind. Daher interpretieren viele Druckertreiber die 
  182. Einstellungen neu. Für den Benutzer ist das häufig nicht einsichtig (wenn
  183. zum Beispiel hinter zwei gleichen Dichten unterschiedliche Tintenstärke
  184. steht). Der Treiber kann nun verschiedene Informationen der Applikation
  185. liefern, die diese im Druckereinsteller anzeigt.
  186.  
  187. Dazu muß zuerst einmal zwischen alten und neuen Treibern unterschieden werden.
  188. Neue Treiber erkennt man an ihrer Version (>= 44) und einem gesetzten Flag
  189. PPCB_EXTENDED in ped_PrinterClass der Struktur PrinterExtendedData
  190. (Include devices/prtbase.h). In diesem Fall enthält der Treiber ein neues
  191. Feld ped_TagList. In dieser Tagliste stehen einige Informationen, die für die
  192. Druckereinstellungen wichtig sind:
  193.  
  194. PRTA_DitherNames: Dieses Tag hat als Wert ein Array mit 3 STRPTRs und 
  195. bezeichnet damit neue Namen für die drei möglichen Dithereinstellungen. 
  196. Bislang waren dies immer "Ordered", "Halftone" und "Floyd-Steinberg". Der
  197. Treiber kann nun neue Namen vorgeben, die seiner Interpretation entsprechen.
  198.  
  199. PRTA_ShadingNames: Dieses Tag hat als Wert ein Array mit 4 STRPTRs und
  200. bezeichnet damit neue Namen für die 4 möglichen Schattiereinstellungen.
  201. Bislang waren dies immer "Black & White", "Grey Scale 1", "Colored" und
  202. "Grey Scale 2". Diese Reihenfolge stimmt so, im Voreinsteller werden sie
  203. überlicherweise umsortiert zu "Black & White", "Grey Scale 1", "Grey Scale 2"
  204. und "Colored". Das Array benutzt allerdings die erste Reihenfolge. Der Treiber
  205. kann nun neue Namen vorgeben, die seiner Interpretation entsprechen (z.B.
  206. für Drucker, die keine Farbe, aber verschiedene Graustufenqualitäten
  207. unterstützen).
  208.  
  209. PRTA_ColorCorrect: Wenn dieses Tag den Wert FALSE hat, so sollten die drei
  210. Häkchen für Rot-, Grün- und Blaukorrektur immer gesperrt sein. Der Treiber
  211. unterstützt dann entweder keine Farbkorrektur oder benutzt andere 
  212. Einstellungen dafür.
  213.  
  214. PRTA_DensityInfo: Dieses Tag hat als Wert ein Array mit 8 STRPTRs. Der erste
  215. String ist derzeit unbenutzt, die 7 folgenden bezeichnen zusätzliche 
  216. Informationen für die Dichten 1 bis 7. Viele Treiber wählen über die Dichte
  217. nicht nur die reine Druckdichte, sonderen auch noch andere Qualitätsmerkmale
  218. des Druckers aus (z.B. Tintenmenge). Diese Strings sollen dem Benutzer darüber
  219. auskunft geben. Natürlich soll aber der Einsteller wie bisher auch noch die
  220. gewählte Dichte in DPI ausgeben (z.B: 300 × 300 DPI), wie sie aus der
  221. PrinterExtendedData ausgelesen werden kann.
  222.  
  223. PRTA_Preferences: Hat dieses Tag einen Wert TRUE, so untersützt der Treiber
  224. zusätzlich eigene Druckereinstellungen. Der Druckereinsteller sollte dann
  225. einen Knopf "Optionen..." freigeben, mit dem der Benutzer die Einstellungen
  226. des Treibers ändern kann. Nähere Erläuterungen dazu folgen unten.
  227.  
  228.  
  229. Änderungen für das Drucken
  230.  
  231. Das Drucken von Text hat sich nicht verändert.
  232.  
  233. Das Drucken von Graphik erlaubt nun die Angabe von RTG Bitmaps. Dabei werden
  234. alle RTG Systeme untertützt, die das CyberGFX API cybergraphics.library
  235. unerstützen. Wenn Die Applikation bislang die Druckausgabe nur mit einer
  236. planaren Bitmap der graphics.library aufgebaut hat oder eine Bitmap eines
  237. dieser RTG Systeme auf 12 oder 8 Bit Farbtiefe konvertiert hat, so kann sie
  238. jetzt direkt die RTG Bitmaps ausgeben. Eine Colormap muß für eine High- (16 bit)
  239. oder Truecolor (24 oder 32 Bit) Bitmap nicht angegeben werden.
  240.  
  241. Der neue Befehl PRD_DUMPRPORTTAGS erweitert den alten Befehl PRD_DUMPRPORT
  242. um eine Tagliste. Derzeit sind 3 Tags definiert und implementiert:
  243.  
  244. DRPA_SouceHook: Der Wert für dieses Tags muß ein Pointer auf eine struct Hook
  245. sein. Dieser Hook wird aufgerufen, um die Quelldaten zu lesen. Der Hook
  246. erhält als object NULL und als message einen Zeiger auf struct DRPSourceMsg.
  247. Diese Struktur enthält die Position und Größe des Arrays, das ausgelesen
  248. werden soll, sowie einen Zeiger auf ein Feld von ULONGs, in die die Daten
  249. geschrieben werden. Dieses Feld hat genau die Größe Breite*Höhe, wie sie
  250. in der message stehen. Jedes Pixel wird als ein ULONG mit der Form
  251. 0x00RRGGBB eingetragen.
  252.  
  253. Typischerweise ist die Höhe für normalen Druck und die Breite für Querdruck
  254. jeweils 1. Ein Programm kann für diesen Fall spezielle Optimierungen 
  255. verwenden, aber muß den allgemeinen Fall auch unterstützen.
  256.  
  257. Benutzt man das Tag DRPA_SourceHook so braucht weder ein RastPort noch eine
  258. Colormap angegeben werden.
  259.  
  260. DRPA_AspectX, DRPA_AspectY: Mit diesen Tags kann man das Seitenverhältnis
  261. der Graphik festlegen. Diese Werte überschreiben die Werte, die normalerweise
  262. aus dem Graphikmodus (io_Modes) oder der GfxBase gewonnen werden. Wenn der
  263. Ausdruck die Skalierung unterdrückt, so wird das Seitenverhältnis ignoriert.
  264.  
  265. Weitere Informationen des Druckertreibers werden wiederum aus der Tagliste
  266. des Treibers ausgelesen:
  267.  
  268. PRTA_LeftBorder und PRTA_TopBorder: Die meisten Drucker haben einen schmalen
  269. Rand auf dem Papier, den sie nicht bedrucken können. Meistens liegt dieser
  270. Rand bei modernen Druckern in der Größenordnung weniger Millimeter. Wenn
  271. eine Applikation auf dem Bildschirm nicht nur den bedruckbaren Bereich des
  272. Papiers, sondern die komplette Seite darstellt, so kann es nun diesen
  273. Rand berücksichtigen: Die beiden Tags geben den linken bzw. oberen Rand
  274. des Papiers in inches/1000 an. Dieser Wert muß je nach Druckerauflösung in
  275. die passende Anzahl Pixel umgerechnet werden (LeftBorder*ped_XDPI/1000 bzw.
  276. TopBorder*ped_YDPI/1000). Geben Sie diese Werte als Offset in den Rastport
  277. an, dessen Bitmap beim Drucken die ganze Seite enthält. Dadurch wird dieser
  278. schmale Rand beim Drucken ausgelassen und der bedruckbare Bereich auf dem
  279. Ausdruck stimmt sehr genau mit der Anzeige auf dem Bildschirm überein.
  280.  
  281. PRTA_MixBWColor: Wenn dieses Tag den Wert TRUE hat, so kann die Applikation
  282. Schwarz/Weiß und Farbausdruck beliebig mischen. Bei Streifendruck kann eine
  283. Applikation, die z.B. viel schwarzen Text und nur selten Graphik im Ausdruck
  284. hat (typische Textverarbeitung) den Ausdruck deutlich beschleunigen, in dem
  285. sie Streifen, die nur schwarzen Text auf weißem Papier enthalten im
  286. Schwarz/Weiß Modus ausdruckt, Streifen mit Graphik und TExt gemischt aber
  287. im Farbmodus. Manche Drucker benutzen jedoch für den Schwarz/Weiß Druck und
  288. den Farbdruck unterschiedliche Farbpatronen oder Tinten, so daß der
  289. Geschwindigkeitsgewinn dahin ist oder eine sehr schlechte Ausdrucksqualität
  290. die Folge ist. Eine Applikation sollte diese Optimierung also unterlassen,
  291. wenn das Tag PRTA_MixBWColor den Wert FALSE hat.
  292.  
  293. Eine weitere Information ist Teil der ped_PrinterClass und kann auch für
  294. alte Treiber zusätzlich gesetzt sein:
  295.  
  296. PPCB_NOSTRIPE: Dieses Flag zeigt einen Druckertreiber an, der nicht in der
  297. Lage ist in Streifen zu drucken. Entweder muß man einem solchen Treiber
  298. die gesamten Druckdaten mit einem einzigen Druckauftrag übergeben 
  299. (insbesondere bei Farbdruck und Auflösungen ab 300 DPI absolut unakzeptabel),
  300. oder den SourceHook DRPA_SourceHook "intelligent" einsetzen, d.h. bei 
  301. Anforderung der Druckdaten durch den Source Hook diese in der Applikation
  302. passend erzeugen.
  303.  
  304. Beachten Sie jedoch, daß der Source Hook immer im Kontext des Treibers
  305. aufgerufen wird. Dieser Kontext ist ein DOS Prozess mit derzeit 4 KByte
  306. Stack. Je nach Konzeptionierung Ihrer Applikation ist es notwendig im
  307. Source Hook mit Hilfe von Exec Messages die Kontrolle an die Applikation
  308. zur Erzeugung eines Druckstreifens zurückzugeben.
  309.  
  310.  
  311. Fehlerbehandlung
  312.  
  313. Die Fehlerbehandlung kann nun komplett dem printer.device überlassen werden.
  314. Bislang konnte das printer.device bzw. ein Druckertreiber nur die Fehler
  315. zurückgeben, deren Fehlercodes in exec/error.h oder devices/printer.h
  316. festgelegt waren. Mit printer.device V44 und neuen Treibern können auch neue
  317. Fehlercodes zurückgegeben werden. Die Formatierung einer lokalisierten
  318. Fehlermeldung erfolgt auf Wunsch aber durch das printer.device oder den
  319. Treiber, die Ausgabe kann entweder auch das printer.device oder die
  320. Applikation übernehmen.
  321.  
  322. Der neue Befehl PRD_SETERRORHOOK erwartet für den IO Request eine Struktur
  323. IOPrtErrReq:
  324.  
  325. struct IOPrtErrReq {
  326.     struct  Message io_Message;
  327.     struct  Device  *io_Device;     /* device node pointer  */
  328.     struct  Unit    *io_Unit;       /* unit (driver private)*/
  329.     UWORD   io_Command;             /* device command */
  330.     UBYTE   io_Flags;
  331.     BYTE    io_Error;               /* error or warning num */
  332.     struct  Hook *io_Hook;
  333. };
  334.  
  335. Das Feld io_Hook kann entweder den Wert PDHOOOK_NONE haben, um die
  336. automatische Fehlerbehandlung abzuschalten oder PDHOOK_STD, um einen
  337. Easy-Requester zur Fehlerausgabe zu benutzen oder einen Pointer auf eine
  338. Struktur Hook. Wird eine I/O Operation des printer.device mit einem
  339. Fehler abgeschlossen, so wird dieser Hook aufgerufen. Dabei enthält
  340. das Objekt einen Pointer auf den I/O Request bei dem der Fehler auftrat
  341. und das Nachrichtpacket einen Pointer auf eine Struktur PrtErrMsg:
  342.  
  343. struct PrtErrMsg {
  344.     ULONG pe_Version; /* Version of this struct */
  345.     ULONG pe_ErrorLevel; /* RETURN_WARN, RETURN_ERROR, RETURN_FAIL */
  346.     struct Window *pe_Window; /* window for EasyRequest() */
  347.     struct EasyStruct *pe_ES;
  348.     ULONG *pe_IDCMP;
  349.     APTR pe_ArgList;
  350. };
  351.  
  352. Das Feld pe_Version enthält den Wert PDHOOK_VERSION (derzeit 1). pe_ErrorLevel
  353. enthält einen Wert RETURN_WARN, RETURN_ERROR oder RETURN_FAIL um die schwere
  354. des Fehlers anzuzeigen. pe_Window enthält einen Pointer auf ein Fenster
  355. oder NULL, dieses Fenster soll dazu benutzt werden, den richtigen Screen
  356. für die Ausgabe zu benutzen. pe_ES enthält eine fertig formatierte
  357. Struktur EasyStruct mit Titel und Text für die Fehlermeldung. pe_IDCMP
  358. kann einen Pointer auf eine Langwort Variable mit IDCMP Flags enthalten, die
  359. einen Requester beenden sollen und pe_ArgList enthält ein Parameterfeld, das
  360. für die Formatierung der Fehlermelung und der Gadgets benutzt werden muß.
  361. Alle Felder können direkt für einen EasyRequest() Aufruf benutzt werden.
  362.  
  363. Der Hook kann in verschiedenen Tasks aufgerufen werden: entweder in dem Task,
  364. der den I/O Request iniziert hat oder in dem Prozess der printer.device
  365. Unit. In zweiten Fall handelt es sich immer um einen DOS Process, so daß
  366. Ausgabe in Dateien oder andere DOS Aufrufe erlaubt sind. Es ist jedoch
  367. kein stdio für diesen Prozess definiert.
  368.  
  369. Der folgende Quelltext ist ein Hook, der den Fehler in einem Easy-Requester
  370. ausgibt.
  371.  
  372. struct Task *ApplicationTask;
  373.  
  374. int easyRequestHook(struct Hook *, struct IORequest *ior, struct PrtErrMsg *msg)
  375. {
  376.     struct Task *me = ApplicationTask;
  377.     if (me->tc_Node.ln_Type != NT_PROCESS
  378.         || ((struct Process *) me)->pr_WindowPtr != (struct Window *) -1)
  379.     {
  380.         struct Window *window = msg->pe_Window;
  381.         if (!window && me->tc_Node.ln_Type == NT_PROCESS)
  382.             window = ((struct Process *) me)->pr_WindowPtr;
  383.         return EasyRequestArgs(msg->pe_Window, msg->pe_ES, msg->pe_IDCMP, msg->pe_ArgList);
  384.     }
  385.     return 0;
  386. }
  387.  
  388. struct Hook StdErrorHook =
  389. {
  390.     { NULL, NULL },
  391.     (HOOKFUNC) HookEntry,
  392.     (HOOKFUNC) easyRequestHook,
  393.     NULL
  394. };
  395.  
  396. Dieser Hook benutzt eine globale Variable ApplicationTask um festzustellen,
  397. ob die Fehlerausgabe unterdrückt werden soll (pt_WindowPtr == -1 bei 
  398. Prozessen) und welches Fenster bei EasyRequestArgs angegeben werden soll, um
  399. den Requester auf dem Screen dieses Fensters zu öffnen. Eine ähnliche
  400. Vorgehensweise benutzt der Hook PDHOOK_STD, allerdings bezieht er sich immer
  401. auf den Task, der die Unit geöffnet hat.
  402.  
  403. Der Fehlerhook muß vor dem Schließen der Unit des printer.device wieder auf
  404. PDHOOK_NONE gesetzt werden.
  405.  
  406.  
  407. Treiberspezifische Einstellungen
  408.  
  409. Die Druckereinstellungen des Voreinstellers "Printer" reichen für viele
  410. moderne Drucker und ihre Treiber nicht mehr aus. Schon seit Version 2.1
  411. hat das AmigaOS für den Post-Script Druckertreiber einen eigenen Einsteller,
  412. mit dem man weiteren Einfluß auf die Ausgabe nehmen kann. Damit solche
  413. Einstellungen auch aus Applikationen verändert werden können wurden
  414. drei neue Druckerbefehle und entsprechende Möglichkeiten für die Treiber
  415. vorgesehen. Um diese Möglichkeiten zu unterstützen müssen sie aus der
  416. Applikation folgendes tun:
  417.  
  418. 1. Testen sie, ob der Treiber eigene Einstellungen unterstützt. Das Tag
  419. PRTA_Preferences ist in diesem Fall TRUE.
  420.  
  421. 2. Sehen sie einen Knopf "Optionen..." in ihrem Druckereinsteller vor. Sperren
  422. sie den Knopf für alte Treiber oder Treiber, die keine eigenen Einstellungen
  423. haben.
  424.  
  425. 3. Wenn der Benutzer den Knopf drückt sperren sie die ganze Oberfläche
  426. und öffnen sie durch den Befehl PRD_EDITPREFS mit DoIO das 
  427. Einstellungsfenster. Das DoIO kehrt zurück, wenn der Benutzer den Einsteller
  428. beendet hat. Der Fehler ist PDERR_CANCEL, wenn der Benutzer den Dialog
  429. abgebrochen hat, sonst 0 (oder ein weiterer Fehler). Der Druckerbefehl
  430. PRD_EDITPREFS erwartet eine Sturktur IOPrtPrefsReq. Diese enthält ein
  431. zusätzliches Feld io_TagList und kennt folgende Tags:
  432.  
  433. PPRA_Window: Pointer auf ein Fenster, das den Screen angibt und für Eingaben
  434. gesperrt wird, solange der Dialog offen ist.
  435.  
  436. PPRA_Screen: Pointer auf einen Screen, falls PPRA_Window nicht angegeben
  437. wird.
  438.  
  439. PPRA_PubScreen: Der Name eines öffentlichen Screen, falls PPRA_Window
  440. nicht angegeben wird.
  441.  
  442. 4. Sollen die Einstellungen, die der Benutzer getroffen hat gespeichert 
  443. werden, oder wird das printer.device zwischen dem Ändern der Einstellungen
  444. geschlossen und wieder geöffnet, so muß das Programm die Einstellungen mit
  445. dem Befehl PRD_READPREFS auslesen. Der Befehl PRD_READPREFS erwartet
  446. eine IOStdReq Struktur. io_Data enthält dabei einen Zeiger auf einen Puffer,
  447. der groß genug sein muß die Daten aufzunehmen, io_Length die Länge des
  448. Puffers, io_Offset muß 0 sein. Eine Länge von 8 KB sollte für die meisten
  449. Fälle genügen, wird der Fehler IOERR_BADLENGTH zurückgegeben, so sollte man
  450. die Puffergröße verdoppeln und nochmal versuchen (bis es funktioniert).
  451.  
  452. LONG buflen = 8192;
  453. LONG err;
  454. for (;;)
  455. {
  456.     if (!(ior->io_Data = AllocVec(buflen,MEMF_PUBLIC)))
  457.     {
  458.         err = PDERR_BUFFERMEMORY;
  459.         break;
  460.     }
  461.     ior->io_Length = buflen;
  462.     ior->io_Offset = 0;
  463.     if ((err = DoIO(ior)) != IOERR_BADLENGTH)
  464.         break;
  465.     FreeVec(ior->io_Data);
  466.     buflen *= 2;
  467. }
  468.  
  469. Die Anzahl der ausgefüllten Bytes im Puffer wird in io_Actual zurückgegeben.
  470. Dieser Puffer ist absolut privat für den Treiber. Er kann nur im Speicher
  471. stehen, byteweise kopiert oder in einer Datei gespeichert werden.
  472.  
  473. 5. Nach dem Öffnen einer printer.device Unit können die zuvor gelesenen
  474. Einstellungen wieder zurückgeschrieben werden. Dazu wird mit dem
  475. Befehl PRD_WRITEPREFS in einer Struktur IOStdReq der Puffer mit den
  476. Preferencesdaten an den Treiber zurückgebenen. io_Data zeigt dabei auf
  477. den Puffer, io_Length bezeichnet die Anzahl der ausgefüllten Bytes im
  478. Puffer (d.h. entspricht dem io_Actual von PRD_READPREFS).
  479.  
  480. Wenn die Applikation die Einstellungen in einer Datei speichert und beim
  481. nächsten Programmlauf wieder benutzt, so kann es natürlich sein, daß der
  482. Benutzer inzwischen den Treiber für diese Unit geändert hat. Die Treiber
  483. erkennen jedoch selbst, ob die Einstellungen für sie bestimmt sind oder
  484. nicht. Deshalb braucht sich die Applikation um diesen Fall nicht zu kümmern.
  485.